﻿
// InjecterDlg.cpp: 实现文件
//

#include "pch.h"
#include <TlHelp32.h>
#include "Injecter.h"
#include "InjecterDlg.h"
#include "afxdialogex.h"


DWORD dPid = 0;		//选中进程的pid
CString dllName;
LPVOID Address;		//注入的DLL地址

// CInjecterDlg 对话框


CInjecterDlg::CInjecterDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG, pParent){

}

void CInjecterDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	//把控件与自定义变量绑定
	DDX_Control(pDX, IDC_PROCCESS_LIST, proccessList);
}

BEGIN_MESSAGE_MAP(CInjecterDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(ID_INJECT, &CInjecterDlg::OnBnClickedInject)
	ON_EN_CHANGE(IDC_SEARCH, &CInjecterDlg::OnEnChangeSearch)
	ON_BN_CLICKED(ID_DEJECT, &CInjecterDlg::OnBnClickedDeject)
END_MESSAGE_MAP()

int defMsg(LPCWSTR msg) {
	return MessageBox(NULL, msg, L"提示信息", NULL);
};

//检查是否选择了进程
CString CheckProccessSelect(CListCtrl* ProccessList) {
	POSITION pos = ProccessList->GetFirstSelectedItemPosition();
	int index = ProccessList->GetNextSelectedItem(pos);
	return ProccessList->GetItemText(index, 0);
}

//绘制进程列表
void DrawProccessList(CListCtrl* proccessList, CString filter) {
	//获取进程列表
	HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
	MODULEENTRY32 me32;
	PROCESSENTRY32 ps32;
	ps32.dwSize = sizeof(PROCESSENTRY32);
	HANDLE HProccessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
	if (HProccessSnap == INVALID_HANDLE_VALUE)
	{
		defMsg(L"CreateToolhelp32Snapshot调用失败!\n");
		return;
	}
	//初始化
	proccessList->DeleteColumn(0);
	proccessList->DeleteColumn(0);
	proccessList->DeleteColumn(0);
	proccessList->DeleteAllItems(); // 全部清空
	//设置表头 参数1:索引 2:内容 3:对齐方式 4:列宽
	proccessList->InsertColumn(0, L"进程ID", LVCFMT_LEFT, 120);
	proccessList->InsertColumn(1, L"进程名", LVCFMT_LEFT, 160);
	proccessList->InsertColumn(2, L"进程路径", LVCFMT_LEFT, 160);
	//设置属性  |整行选中|显示网格
	proccessList->SetExtendedStyle(proccessList->GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	int x = 0;
	CString pDataId;
	CString pDataName;
	CString pDataPath;
	Process32First(HProccessSnap, &ps32);
	while (Process32Next(HProccessSnap, &ps32)) {
		pDataPath.Format(L"");
		pDataId.Format(L"%d", ps32.th32ProcessID);
		pDataName.Format(ps32.szExeFile);
		hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ps32.th32ProcessID);
		if (hModuleSnap != INVALID_HANDLE_VALUE)
		{
			me32.dwSize = sizeof(MODULEENTRY32);
			Module32First(hModuleSnap, &me32);
			pDataPath.Append(me32.szExePath);
		}
		if (filter && !filter.IsEmpty()) {
			if (pDataName.Left(filter.GetLength()).MakeLower() != filter.MakeLower()) {
				continue;
			}
		}
		proccessList->InsertItem(x, pDataId);
		proccessList->SetItemText(x, 1, pDataName);
		proccessList->SetItemText(x, 2, pDataPath);
		x++;
	}
	CloseHandle(HProccessSnap);
}

// CInjecterDlg 消息处理程序

BOOL CInjecterDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	GetDlgItem(IDC_SEARCH)->SetWindowTextW(L"输入进程名");

	//绘制进程
	DrawProccessList((CListCtrl*)GetDlgItem(IDC_PROCCESS_LIST), NULL);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}


//退出按钮按下
void CInjecterDlg::OnBnClickedClose()
{
	AfxGetMainWnd()->SendMessage(WM_CLOSE);
}

//开始注入
void CInjecterDlg::OnBnClickedInject()
{
	CString pid = CheckProccessSelect((CListCtrl*)GetDlgItem(IDC_PROCCESS_LIST));
	if (pid.IsEmpty()) {
		defMsg(L"请选择进程");
		return;
	}
	//选择dll文件
	CString gReadFilePathName;
	CFileDialog fileDlg(
		true
		, _T("dll")
		, _T("*.dll")
		, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
		, _T("dll Files (*.dll)|*.dll|All Files (*.*)|*.*||")
		, NULL
	);
	if (fileDlg.DoModal() == IDOK)    //弹出对话框  
	{
		gReadFilePathName = fileDlg.GetPathName();//得到完整的文件名和目录名拓展名  

		//打开句柄
		dPid = _ttoi(pid);
		HANDLE hProccess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dPid);
		if (NULL == hProccess) {
			defMsg(L"打开进程失败");
			return;
		}

		DWORD AddrLen = gReadFilePathName.GetAllocLength() * 2;
		//申请内存
		Address = VirtualAllocEx(hProccess, NULL, AddrLen, MEM_COMMIT, PAGE_READWRITE);
		if (NULL == Address) {
			defMsg(L"内存申请失败");
			return;
		}
		//注入DLL
		if (0 == WriteProcessMemory(hProccess, Address, gReadFilePathName, AddrLen, NULL)) {
			defMsg(L"注入DLL失败");
			return;
		} 
		//执行DLL
		HMODULE k32 = GetModuleHandleA("Kernel32.dll");
		if (0 == k32) {
			defMsg(L"获取本地Kernal32库地址失败");
			return;
		}
		LPVOID loadLibAddr = GetProcAddress(k32, "LoadLibraryW");
		HANDLE hRemoteThread = CreateRemoteThread(hProccess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibAddr, Address, 0, NULL);
		if (NULL == hRemoteThread) {
			defMsg(L"执行DLL失败");
			return;
		}

		CloseHandle(hRemoteThread);
		CloseHandle(hProccess);

		CString cAddr;
		cAddr.Format(L"Address:%p File:", Address);
		gReadFilePathName.Insert(0, cAddr);
		GetDlgItem(IDC_FILE_PATH)->SetWindowText(gReadFilePathName);//将路径显示
		dllName = fileDlg.GetFileName();
	}
}

//搜索功能
void CInjecterDlg::OnEnChangeSearch()
{
	CString search;
	CString def(L"输入进程名");
	GetDlgItemText(IDC_SEARCH, search);
	if (search != def) {
		//绘制进程
		DrawProccessList((CListCtrl*)GetDlgItem(IDC_PROCCESS_LIST), search);
	}
}

BOOL UnLoadDll(LPCTSTR szDllName, DWORD dwID)//要卸载的DLL名，进程PID
{
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwID);
    if ( !hProcess ) {
        return FALSE;
    }
    int cByte  = (_tcslen(szDllName)+1) * sizeof(TCHAR);
    LPVOID pAddr = VirtualAllocEx(hProcess, NULL, cByte, MEM_COMMIT, PAGE_READWRITE);
    if ( !pAddr || !WriteProcessMemory(hProcess, pAddr, szDllName, cByte, NULL)) {
        return FALSE;
    }
#ifdef _UNICODE
    PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetModuleHandleW;
#else
    PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetModuleHandleA;
#endif
    //Kernel32.dll总是被映射到相同的地址
    if ( !pfnStartAddr ) {
        return FALSE;
    }
    DWORD dwThreadID = 0,dwFreeId=0,dwHandle;
    HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAddr, pAddr, 0, &dwThreadID);
    if ( !hRemoteThread ) {
        return FALSE;
    }
    WaitForSingleObject(hRemoteThread,INFINITE);
    // 获得GetModuleHandle的返回值
    GetExitCodeThread(hRemoteThread,&dwHandle);
    CloseHandle(hRemoteThread);
    // 使目标进程调用FreeLibrary，卸载DLL
#ifdef _UNICODE
    PTHREAD_START_ROUTINE pfnFreeAddr = (PTHREAD_START_ROUTINE)FreeLibrary;
#else
    PTHREAD_START_ROUTINE pfnFreeAddr = (PTHREAD_START_ROUTINE)FreeLibrary;
#endif
    HANDLE hFreeThread = CreateRemoteThread(hProcess, NULL, 0, pfnFreeAddr,(LPVOID)dwHandle,0,&dwFreeId);
    if ( !hFreeThread ) {
        return FALSE;
    }
    WaitForSingleObject(hFreeThread,INFINITE);
    VirtualFreeEx(hProcess,pAddr,cByte,MEM_COMMIT);
    CloseHandle(hFreeThread);    
    CloseHandle(hProcess);
    return TRUE;
}

//卸载DLL
void CInjecterDlg::OnBnClickedDeject()
{
	if (0 == dPid) {
		defMsg(L"请先执行注入操作");
		return;	
	}
	if (UnLoadDll(dllName, dPid)) {
		defMsg(L"DLL卸载成功");
	}
	else {
		defMsg(L"DLL卸载失败");
	}
}
